package COSC455Compiler;

import edu.towson.cosc.cosc455.interfaces.SyntaxAnalyzer;

public class MySyntaxAnalyzer implements SyntaxAnalyzer {

    public void lolcode() {
        MyCompiler.Lexer.getNextToken();
        if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.Doc_Begin)) {
            System.err.println("Syntax Error: " + MyCompiler.token + "when " + LexicalTokens.Doc_Begin + "was expected");
            System.exit(0);
        } else {
            MyCompiler.Lexer.getNextToken();
        }

        if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Head_Begin)) {
            head();
            MyCompiler.Lexer.getNextToken();
        }
        if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Comment_Begin)) {
            comment();
        }

        body();

        if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.Doc_End)) {
            System.err.println("Syntax Error: " + MyCompiler.token + "when "
                    + LexicalTokens.Doc_End + "was expected.");
            System.exit(0);
        }
    }

    public void body() {
        MyCompiler.Lexer.getNextToken();

        if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Comment_Begin)) {
            comment();
            body();
        } else if ((MyCompiler.token.equalsIgnoreCase(LexicalTokens.NewLine_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Visible_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Audio_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Video_Begin))) {
            Inner_Text();
            body();
        } else if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Paragraph_Begin)) {
            paragraph();
            body();
        } else if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.List_Begin)) {
            list();
            body();
        } else if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Bold_Begin)) {
            bold();
            body();
        } else if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Italics_Begin)) {
            italics();
            body();
        } else if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.Doc_End)) {
            body();
        }
    }

    public void Inner_Paragraph() {
        if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Bold_Begin)) {
            bold();
        } else if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Italics_Begin)) {
            italics();
        } else if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.List_Begin)) {
            list();
        } else if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.NewLine_Begin)) {
            NewLine();
        } else if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Visible_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Audio_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Video_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.NewLine_Begin)) {
            Inner_Text();
        } else {
            System.err.println("Syntax Error: " + MyCompiler.token + "when inner paragaraph was expected.");
            System.exit(0);
        }
    }

    public void Inner_Text() { // Add use_variable
        if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Visible_Begin)) {
            use();
        } else if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Audio_Begin)) {
            audio();
        } else if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Video_Begin)) {
            video();
        } else if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.NewLine_Begin)) {
            NewLine();
        } else {
            System.err.println("Syntax Error: " + MyCompiler.token + "when inner paragaraph was expected.");
            System.exit(0);
        }
    }
    
    public void Inner_List() {
        if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Bold_Begin)) {
            bold();
        } else if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Italics_Begin)) {
            italics();
        } else if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.List_Begin)) {
            list();
        } else if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Visible_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Audio_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Video_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.NewLine_Begin)) {
            Inner_Text();
        } else {
            System.err.println("Syntax Error: " + MyCompiler.token + "when inner paragaraph was expected.");
            System.exit(0);
        }
    }
    
    // ________________________________________________________________________________________________________
    public void comment() {
        MyCompiler.Lexer.getNextToken();// get token
        if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.Comment_END)) {
            System.err.println("Syntax Error: " + MyCompiler.token + "when "+ LexicalTokens.Comment_END + "was expected.");
            System.exit(0);
        }
    }

    public void head() {
        MyCompiler.Lexer.getNextToken();// get token
        if ((MyCompiler.token.equalsIgnoreCase(LexicalTokens.Title_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Head_END))) {
            if (!(MyCompiler.token.equalsIgnoreCase(LexicalTokens.Head_END))) {
                title();
            }
        } else {
            System.err.println("Syntax Error: " + MyCompiler.token + "when Begin Title or Head End was expected.");
            System.exit(0);
        }
    }

    public void title() {
        MyCompiler.Lexer.getNextToken();
        if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.Title_END)) {
            System.err.println("Syntax Error: " + MyCompiler.token + "when " + LexicalTokens.Title_END + "was expected.");
            System.exit(0);
        }
    }

    public void paragraph() {
        MyCompiler.Lexer.getNextToken();
        if (LexicalTokens.Variable_Begin.equalsIgnoreCase(MyCompiler.token)) {
            define();
            MyCompiler.Lexer.getNextToken();
        }
        if (!(LexicalTokens.Bold_Begin.equalsIgnoreCase(MyCompiler.token)
                || LexicalTokens.Italics_Begin.equalsIgnoreCase(MyCompiler.token)
                || LexicalTokens.List_Begin.equalsIgnoreCase(MyCompiler.token)
                || LexicalTokens.NewLine_Begin.equalsIgnoreCase(MyCompiler.token)
                || LexicalTokens.Visible_Begin.equalsIgnoreCase(MyCompiler.token)
                || LexicalTokens.Audio_Begin.equalsIgnoreCase(MyCompiler.token)
                || LexicalTokens.Video_Begin.equalsIgnoreCase(MyCompiler.token))) {

            do {
                if (LexicalTokens.Bold_Begin.equalsIgnoreCase(MyCompiler.token)
                        || LexicalTokens.Italics_Begin.equalsIgnoreCase(MyCompiler.token)
                        || LexicalTokens.List_Begin.equalsIgnoreCase(MyCompiler.token)
                        || LexicalTokens.NewLine_Begin.equalsIgnoreCase(MyCompiler.token)) {
                    Inner_Paragraph();
                } else if (LexicalTokens.Visible_Begin.equalsIgnoreCase(MyCompiler.token)
                        || LexicalTokens.Audio_Begin.equalsIgnoreCase(MyCompiler.token)
                        || LexicalTokens.Video_Begin.equalsIgnoreCase(MyCompiler.token)
                        || LexicalTokens.NewLine_Begin.equalsIgnoreCase(MyCompiler.token)) {
                    Inner_Text();
                }

            } while (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.Paragraph_END));
        }
    }

    public void bold() {
        MyCompiler.Lexer.getNextToken();
        if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Variable_Begin)) {
            define();
            MyCompiler.Lexer.getNextToken();
        }
        if ((MyCompiler.token.equalsIgnoreCase(LexicalTokens.NewLine_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Visible_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Audio_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Video_Begin))) {
            do {
                Inner_Text();
            } while (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.Bold_END));
        }
    }

    public void italics() {
        MyCompiler.Lexer.getNextToken();
        if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Variable_Begin)) {
            define();
            MyCompiler.Lexer.getNextToken();
        }
        if ((MyCompiler.token.equalsIgnoreCase(LexicalTokens.NewLine_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Visible_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Audio_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Video_Begin))) {
            do {
                Inner_Text();
            } while (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.Italics_END));
        }
    }

    // This needs to be looped somehow
    public void list() {
        MyCompiler.Lexer.getNextToken();
        if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.Item_Begin)) {
            MyCompiler.Lexer.getNextToken();
            if ((MyCompiler.token.equalsIgnoreCase(LexicalTokens.NewLine_Begin)
                    || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Visible_Begin)
                    || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Audio_Begin)
                    || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Video_Begin))) {
                do {
                    Inner_Text();
                } while (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.Item_END));
            }
        }
    }

    public void audio() {
        MyCompiler.Lexer.getNextToken();
        if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.Audio_END)) {
            System.err.println("Syntax Error: " + MyCompiler.token + " when " + LexicalTokens.Audio_END + " was expected.");
            System.exit(0);
        }
    }

    public void video() {
        MyCompiler.Lexer.getNextToken();
        if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.Video_END)) {
            System.err.println("Syntax Error: " + MyCompiler.token + " when " + LexicalTokens.Video_END + " vid was expected.");
            System.exit(0);
        }
    }

    public void use() {
        MyCompiler.Lexer.getNextToken();
        if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.Visible_END)) {
            System.err.println("Syntax Error: " + MyCompiler.token + " when "
                    + LexicalTokens.Visible_END + " was expected.");
            System.exit(0);
        }
    }

    public void NewLine() {
        //MyCompiler.ParseTree.add(MyCompiler.token);
    }

    public void item() {
        MyCompiler.Lexer.getNextToken();
        if ((MyCompiler.token.equalsIgnoreCase(LexicalTokens.NewLine_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Visible_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Audio_Begin)
                || MyCompiler.token.equalsIgnoreCase(LexicalTokens.Video_Begin))) {
            do {
                Inner_Text();
            } while (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.Item_END));
        }
    }

    public void define() {        // #I HAS A <text> #ITZ <text> #MKAY <variable-define> | ε
        MyCompiler.Lexer.getNextToken();
        if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.Its)) {
            System.err.println("Syntax Error: " + MyCompiler.token + "when " + LexicalTokens.Its + "was expected.");
            System.exit(0);
        } else {
            if (MyCompiler.token.contains("#")) {
                MyCompiler.Lexer.getNextToken();
                if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.Variable_END)) {
                    System.err.println("Syntax Error: " + MyCompiler.token + "when " + LexicalTokens.Variable_END + "was expected.");
                    System.exit(0);
                }
            } else {
                System.err.println("Syntax Error: " + MyCompiler.token + " when text was expected.");
                System.exit(0);
            }
        }
    }
}